package leetcode.interviewClassics;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * @author Cheng Jun
 * Description: 堆盘子。设想有一堆盘子，堆太高可能会倒下来。因此，在现实生活中，
 * 盘子堆到一定高度时，我们就会另外堆一堆盘子。请实现数据结构SetOfStacks，
 * 模拟这种行为。SetOfStacks应该由多个栈组成，并且在前一个栈填满时新建一个栈。
 * 此外，SetOfStacks.push()和SetOfStacks.pop()应该与普通栈的操作方法相同（也就是说，pop()返回的值，
 * 应该跟只有一个栈时的情况一样）。 进阶：实现一个popAt(int index)方法，根据指定的子栈，执行pop操作。
 * <p>
 * 当某个栈为空时，应当删除该栈。当栈中没有元素或不存在该栈时，pop，popAt 应返回 -1.
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/stack-of-plates-lcci
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * @version 1.0
 * @date 2021/11/4 13:38
 */
public class StackOfPlates {
    private List<Stack<Integer>> stackList;
    private int cap;
    public StackOfPlates(int cap) {
        this.stackList = new ArrayList<>();
        this.cap = cap;
    }

    public static void main(String[] args) {
        StackOfPlates stackOfPlates = new StackOfPlates(2);
        stackOfPlates.push(1);
        stackOfPlates.push(2);
        stackOfPlates.push(3);
        stackOfPlates.popAt(0);
        stackOfPlates.popAt(0);
        stackOfPlates.popAt(0);
    }

    public void push(int val) {
        Stack<Integer> integerStack;
        if (stackList.size() == 0) {
            integerStack = new Stack<>();
            stackList.add(integerStack);
        } else {
            integerStack = stackList.get(stackList.size() - 1);
        }
        // 栈满时，插入就要先建栈
        if (integerStack.size() == cap) {
            Stack<Integer> nextIntegerStack = new Stack<>();
            nextIntegerStack.push(val);
            stackList.add(nextIntegerStack);
        } else {
            integerStack.push(val);
        }
    }

    public int pop() {
        if (stackList.size() == 0) {
            return -1;
        }
        Stack<Integer> integerStack = stackList.get(stackList.size() - 1);
        if (integerStack.size() == 0) {
            return -1;
        }
        Integer pop = integerStack.pop();
        // 如果integerStack 没有元素了，pop后要把这个 integerStack 从list中移除
        if (integerStack.size() == 0) {
            stackList.remove(integerStack);
        }
        return pop;
    }

    public int popAt(int index) {
        Stack<Integer> integerStack;
        if (stackList.size() == 0) {
            integerStack = new Stack<>();
            stackList.add(integerStack);
        } else {
            integerStack = stackList.get(index);
        }
        Integer pop = integerStack.pop();
        if (integerStack.size() == 0) {
            stackList.remove(integerStack);
        }
        return pop;
    }
}
